home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / ScreenSavers / BackSpaceViews / StarShipView.BackModule / StarShipView.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  13.3 KB  |  574 lines

  1. #import "StarShipView.h"
  2. #import "NewSpaceView.h"
  3. #import "Thinker.h"
  4. #import <stdio.h>
  5. #import "StarShipProtocol.h"
  6. #import <dpsclient/wraps.h>
  7.  
  8.  
  9. #define sliderDelay    2000
  10.  
  11. @implementation StarShipView
  12.  
  13. static char **bundleFilenameList;
  14.  
  15.  
  16. + initialize
  17. {
  18.     if ( self == [StarShipView class] )
  19.     {
  20.        static NXDefaultsVector starShipDefs = {
  21.         {"StarShipObjectSpeed",        "180"},
  22.         {"StarShipIntervalTime",    "5"},
  23.         {"StarShipAnimationSpeed",    "500"},
  24.         {"StarShipCycleCount",    "250"},
  25.         {"StarShipSound",    "1"},
  26.         {"StarShipStarSpeed",    "1"},
  27.         {NULL}
  28.        };
  29.  
  30.        NXRegisterDefaults([NXApp appName], starShipDefs);
  31.     }
  32.     return self;
  33. }
  34.  
  35. - oneStep
  36. {
  37.     if (viewScreenResized){ //tell everybody about it
  38.         if(controllerTypeCount > 0){
  39.             [spaceTypeController setBoundsRect: &newViewScreenSize];
  40.             //set new clip area
  41.             NXSetRect(&clipRect,newViewScreenSize.origin.x,
  42.              newViewScreenSize.origin.y,newViewScreenSize.size.width,
  43.              newViewScreenSize.size.height);
  44.              // numbers have to do with size of the viewscreen border
  45.             clipRect.origin.x += 3.0;
  46.             clipRect.origin.y += 3.0;;
  47.             clipRect.size.width -= 6.0;
  48.             clipRect.size.height -= 6.0;
  49.             rectPtr = &clipRect;
  50.         }
  51.         viewScreenResized = NO;        
  52.  
  53.     }
  54.     if (controllerTypeCount > 0){   // they exist
  55.         NXRectClip(rectPtr);  //clip to screen border
  56.         if ([spaceTypeController doUntilDone]){
  57.             [spaceTypeController freeResources];
  58.             controllerIndex++;
  59.             if (controllerIndex >= controllerTypeCount)
  60.                 controllerIndex = 0;
  61.             spaceTypeController =  [controllerList
  62.             objectAt:controllerIndex];
  63.             if(soundGood){
  64.                 [spaceTypeController setPwrDownSnd:pwrDownSnd];
  65.                 [spaceTypeController setPwrUpSnd:pwrUpSnd];
  66.             }
  67.             [self setModuleBox];  //update module info in inspector window    
  68.  
  69.             [viewScreen setBodyControllerOutlet:spaceTypeController];
  70.             [spaceTypeController setStarsOutlet:viewScreen];
  71.             //send module all slider values
  72.             firstTimeSound = 1;  //don't want to play sound at startup
  73.             [self setSound:soundMatrix];
  74.             [self setStarSpeed:starSpeedSlider];
  75.             [self setAnimationSpeed:animationSlider];
  76.             [self setObjectInterval:objectIntervalSlider];
  77.             [self setObjectSpeed:objectSpeedSlider];
  78.             [self setCycleCount:cycleCountSlider];
  79.             [spaceTypeController setBoundsRect: &newViewScreenSize];
  80.             [spaceTypeController setFirstState];
  81.  
  82.             
  83.         }
  84.         PSinitclip();    //turn off clipping
  85.     }
  86.     
  87.     [viewScreen oneStep];
  88.  
  89.     if(frameRate > 1)
  90.         xmach_sleep(port, frameRate);
  91.  
  92.     return self;
  93.  
  94. }
  95. - (BOOL)makeSndObjects: (char *)directory
  96. {
  97. char buf[MAXPATHLEN + 1];
  98.     
  99.     soundGood = YES;
  100.     sprintf(buf,"%s/pwrDown.snd",directory);
  101.     pwrDownSnd = [[Sound alloc] initFromSoundfile:buf];
  102.     if(pwrDownSnd == nil){
  103.         soundGood = NO;
  104.         printf("unable to create sound object %s\n",buf);
  105.     }
  106.     sprintf(buf,"%s/pwrUp.snd",directory);
  107.     pwrUpSnd = [[Sound alloc] initFromSoundfile:buf];
  108.     if(pwrUpSnd == nil){
  109.         soundGood = NO;
  110.         printf("unable to create sound object %s\n",buf);
  111.     }
  112.     sprintf(buf,"%s/sound.snd",directory);
  113.     sound = [[Sound alloc] initFromSoundfile:buf];
  114.     if(sound == nil){
  115.         soundGood = NO;
  116.         printf("unable to create sound object %s\n",buf);
  117.     }
  118.     return soundGood;
  119. }
  120.  
  121. //*********************************
  122. // this builds a list of bundles in the StarShipView.BackModule bundle
  123. // and instantiates first bundle object
  124. // there must be a class object that is same as bundle name
  125. // The idea here is build a list of space object controllers
  126. // like celestial body controllers, ship controllers, etc
  127.  
  128. - buildControllerList: (char *)directory
  129. {
  130. NXBundle * tmpBundle;
  131. char buf[MAXPATHLEN + 1];    
  132. short ii,successCount;
  133.     
  134.     controllerTypeCount = [self searchDirectory: directory];
  135.     controllerList = [[List alloc] initCount:controllerTypeCount];
  136.     
  137.     successCount = 0;
  138.     if(controllerTypeCount > 0){//there are some
  139.         successCount = 0;
  140.         for(ii = 0; ii < controllerTypeCount; ii++){
  141.             sprintf(buf,"%s/%s.bundle",directory,bundleFilenameList[ii]);
  142.  
  143.             if((tmpBundle = [[NXBundle alloc] initForDirectory:buf]) == nil)
  144.                 printf("could not create bundle object for %s\n",buf);
  145.             else {
  146.                 if((spaceTypeController = [[[tmpBundle
  147.                  classNamed:bundleFilenameList[ii]]alloc]init])){
  148.                     successCount++;
  149.                     [controllerList addObject:spaceTypeController];
  150.                 }
  151.             }
  152.        
  153.         }
  154.     controllerTypeCount = successCount;
  155.     }         
  156.     return self;
  157. }
  158.     
  159. static BOOL isOk(const char *filename)
  160. /* checks to make sure the filename is .bundle
  161.  */
  162. char *suffix;
  163.  
  164.     suffix = rindex(filename,'.');
  165.     if (suffix == 0)
  166.         return NO;
  167.     else if(strlen(suffix) != 7)
  168.         return NO;
  169.     else
  170.         return(strncmp(suffix,".bundle",7)) ? NO : YES;  
  171.  
  172. }
  173.  
  174. #define CHUNK 127
  175. static char **addFile(const char *file, int length, char **list, int count)
  176. /* Adds the specified filename to the list of filenames.  It allocates 
  177.  * more memory in chunks as needed.
  178.  */
  179. {
  180.     char *suffix;
  181.    
  182.     if (!list) list = (char **)malloc(CHUNK*sizeof(char *));
  183.     if (suffix = rindex(file,'.')) 
  184.         *suffix  = '\0';     /* strip .bundle suffix */
  185.     list[count] = (char *)malloc((length+1)*sizeof(char));
  186.     strcpy(list[count], file);
  187.     count++;
  188.     if (!(count% CHUNK)) {
  189.     list = (char **)realloc(list,(((count/CHUNK)+1)*CHUNK)*sizeof(char *));
  190.     }
  191.     list[count] = NULL;
  192.     return list;
  193. }
  194.  
  195. static void freeList(char **list)
  196. /* Frees the array of filenames
  197.  */
  198.  {
  199.     char **strings;
  200.     if (list) {
  201.     strings = list;
  202.     while (*strings) free(*strings++);
  203.     free(list);
  204.     }
  205. }
  206.  
  207.  
  208. // look in the right bundle directory for all the space object bundles
  209. // create a list called bundleFilenameList
  210. - (int)searchDirectory: (char *)directory
  211.  
  212. {
  213.     long basep;
  214.     char *buf;
  215.     struct direct *dp;
  216.     char **list = NULL;
  217.     int cc, fd, fileCount = 0;
  218.     char dirbuf[8192];
  219.  
  220.     if ((fd = open(directory, O_RDONLY, 0644)) > 0) {
  221.     cc = getdirentries(fd, (buf = dirbuf), 8192, &basep);
  222.     while (cc) {
  223.         dp = (struct direct *)buf;
  224.         
  225.         if (isOk(dp->d_name)) {
  226.         list = addFile(dp->d_name, dp->d_namlen, list, fileCount++);
  227.         }
  228.         buf += dp->d_reclen;
  229.         if (buf >= dirbuf + cc) {
  230.         cc = getdirentries(fd, (buf = dirbuf), 8192, &basep);
  231.         }
  232.     }
  233.     close(fd);
  234.     }
  235.  
  236.     freeList(bundleFilenameList);
  237.     bundleFilenameList = list;
  238.     return fileCount;
  239. }
  240.  
  241. - sizeTo:(NXCoord)width :(NXCoord)height
  242. {
  243.     [super sizeTo:width :height];
  244.  
  245.     [viewScreen sizeTo:width :height];//send original size to space
  246.     
  247.     if(controllerTypeCount > 0){
  248.         [spaceTypeController setBoundsRect:&newViewScreenSize];
  249.         NXSetRect(&clipRect,newViewScreenSize.origin.x,
  250.             newViewScreenSize.origin.y,
  251.             newViewScreenSize.size.width,newViewScreenSize.size.height);
  252.         clipRect.origin.x += 3.0;
  253.         clipRect.origin.y += 3.0;;
  254.         clipRect.size.width -= 6.0;
  255.         clipRect.size.height -= 6.0;
  256.         rectPtr = &clipRect;
  257.         
  258.     [spaceTypeController windowSizeChanged];    
  259.     
  260.     }
  261.             
  262.     return self;
  263. }
  264.  
  265.  
  266.  
  267. - initFrame:(const NXRect *)frameRect
  268. {
  269. char buf[MAXPATHLEN + 1];
  270.  
  271.     [super initFrame:frameRect];
  272.     [self allocateGState];        // For faster lock/unlockFocus
  273.     [self inspector:self];      //this guarantees that sliders exist when I
  274.                                 //set them    
  275.     moduleDir = [[NXApp delegate] moduleDirectory:"StarShip"];
  276.     strcpy(buf, moduleDir);
  277.     
  278.  
  279.     viewScreen = [[NewSpaceView alloc] initFrame:frameRect];
  280.     [viewScreen setStarShipOutlet:self];
  281.  
  282.     NXSetRect(&clipRect,newViewScreenSize.origin.x,
  283.      newViewScreenSize.origin.y,
  284.      newViewScreenSize.size.width,newViewScreenSize.size.height);
  285.     clipRect.origin.x += 3.0;
  286.     clipRect.origin.y += 3.0;;
  287.     clipRect.size.width -= 6.0;
  288.     clipRect.size.height -= 6.0;
  289.     rectPtr = &clipRect;
  290.  
  291.     
  292.     // builds list of bundle objects
  293.     [self buildControllerList:buf];
  294.     controllerIndex = 0;
  295.     spaceTypeController =  [controllerList objectAt:controllerIndex];
  296.     if([self makeSndObjects:buf]){
  297.         [spaceTypeController setPwrDownSnd:pwrDownSnd];
  298.         [spaceTypeController setPwrUpSnd:pwrUpSnd];
  299.     }
  300.     [self setModuleBox];  //update module info in inspector window    
  301.     
  302.     [spaceTypeController setBoundsRect: (NXRect *)frameRect];
  303.  
  304.     [spaceTypeController setStarsOutlet:viewScreen];
  305.  
  306.  
  307.     [viewScreen setBodyControllerOutlet:spaceTypeController];
  308.  
  309.     [self getDefaults:self];
  310.     firstTimeSound = 1;  //don't want to play sound at startup
  311.     [self setSound:soundMatrix];
  312.     [self setStarSpeed:starSpeedSlider];
  313.     [self setAnimationSpeed:animationSlider];
  314.     [self setObjectInterval:objectIntervalSlider];
  315.     [self setObjectSpeed:objectSpeedSlider];
  316.     [self setCycleCount:cycleCountSlider];
  317.     [spaceTypeController setFirstState];
  318.     
  319.     port = xmach_sleep_install();
  320.     viewScreenResized = NO;
  321.     
  322.     return self;
  323. }
  324. - setCycleCount:(Slider *)sender
  325. {
  326. int    multiplier,value;;
  327.  
  328.     // real slider value min is 0
  329.     //I show a min of 1 cycle in the cycleCountBox
  330.     value = [sender intValue];
  331.     multiplier = (int)[spaceTypeController setCycleValue:value];
  332.     if (value == 0)
  333.         value = 1;
  334.     else
  335.         value *= multiplier;
  336.     [cycleCountBox setIntValue:value];
  337.  
  338.     [self delayedDefaults:self];
  339.     return self;
  340. }
  341. - setStarSpeed:(Slider *)sender
  342. {
  343.     [viewScreen setStarSpeed:sender];
  344.     [spaceTypeController setStarSpeed:sender];
  345.     [self delayedDefaults:self];
  346.  
  347.     return self;
  348. }
  349.  
  350. - setAnimationSpeed:(Slider *)sender
  351. {
  352.     frameRate = ([sender maxValue] + [sender minValue]) - [sender intValue];
  353.     [self delayedDefaults:self];
  354.  
  355.     return self;
  356. }
  357. - setObjectSpeed:(Slider *)sender
  358. {
  359.     [spaceTypeController setObjectSpeed:sender];
  360.     [self delayedDefaults:self];
  361.  
  362.     return self;
  363. }
  364. - setObjectInterval:(Slider *)sender
  365. {
  366.     [spaceTypeController setStartInterval: sender];//send slider to current
  367.     [self delayedDefaults:self];                     //space object
  368.     return self;
  369. }
  370. - setSound:sender
  371. {
  372.  
  373.     if(soundGood){  //there are valid sound files
  374.         if(!firstTimeSound)
  375.             [sound play];
  376.         firstTimeSound = 0;
  377.         soundEnabled = (BOOL)[[sender selectedCell] tag];
  378.         [spaceTypeController setSoundEnabled:soundEnabled];
  379.     }
  380.     else{  //set all sound off permanently
  381.         soundEnabled = NO;
  382.         [spaceTypeController setSoundEnabled:soundEnabled];
  383.     
  384.     }
  385.     [self delayedDefaults:self];
  386.     
  387.     return self;
  388. }
  389. - setModuleBox
  390. {
  391.     [moduleBox setStringValue:bundleFilenameList[controllerIndex]];
  392.     return self;
  393. }
  394.  
  395.  
  396. - didLockFocus
  397. {
  398.     [viewScreen didLockFocus];
  399.     return self;
  400. }
  401.  
  402. - (const char *) windowTitle
  403. {
  404.     return("StarShip!");
  405. }
  406.  
  407. - inspector:sender
  408. {
  409.     char buf[MAXPATHLEN];
  410.     
  411.     if (!inspectorPanel)
  412.     {
  413.         sprintf(buf,"%s/English.lproj/StarShip.nib",[[NXApp delegate]
  414.         moduleDirectory:"StarShip"]);
  415.         if([NXApp loadNibFile:buf owner:self withNames:NO] == nil)
  416.             printf ("inspector not loaded %s\n",buf);
  417.     }
  418.     return inspectorPanel;
  419. }
  420.  
  421. - inspectorWillBeRemoved
  422. {
  423.     [[infoText window] orderOut:self];
  424.     return self;
  425. }
  426.  
  427. // The module is never freed
  428. // but it's here in case backSpace ever wants to ;-)
  429.  
  430. - free
  431. {
  432.     //This is untested!!!!
  433.     
  434.     [controllerList freeObjects];
  435.     [controllerList free];
  436.     [pwrDownSnd free];
  437.     [pwrUpSnd free];
  438.     [sound free];
  439.     freeList(bundleFilenameList);
  440.     xmach_sleep_remove(port);
  441.     return [super free];
  442. }
  443.  
  444.  
  445. // I left this in in case some of the modules wanted to do 
  446. //something cool with mouse
  447. //down events  - it is not functional right now
  448.  
  449. /*- mouseDown:(NXEvent *)theEvent;
  450. {
  451.     NXRect            r;
  452.     NXPoint            p;
  453.     unsigned int    i;
  454.  
  455.     p = theEvent->location;
  456.     [self convertPoint:&p fromView:nil];
  457.  
  458.     [self lockFocus];
  459.     [spaceTypeController doSomethingNow];
  460.     [self unlockFocus];
  461.  
  462.     return self;
  463. }*/
  464. //needed for mouse down events
  465. /*- newWindow
  466. {
  467.     shipWindow = [self window];
  468.     [shipWindow addToEventMask:NX_LMOUSEDOWNMASK];
  469.     return self;
  470. }*/
  471.  
  472. - delayedDefaults:sender
  473. {
  474.     [self perform:@selector(writeDefaults:) with:self afterDelay:sliderDelay
  475.      cancelPrevious:YES];
  476.     return self;
  477. }
  478.  
  479.  
  480. - getDefaults:sender
  481. {
  482. int cell;
  483.     [animationSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
  484.      "StarShipAnimationSpeed"))];
  485.     
  486.     [objectSpeedSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
  487.      "StarShipObjectSpeed"))];
  488.     
  489.     [starSpeedSlider setFloatValue:atof(NXGetDefaultValue([NXApp appName],
  490.      "StarShipStarSpeed"))];
  491.  
  492.  
  493.     [objectIntervalSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
  494.      "StarShipIntervalTime"))];
  495.     
  496.     [cycleCountSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
  497.      "StarShipCycleCount"))];
  498.  
  499.     [cycleCountBox setIntValue:atoi(NXGetDefaultValue([NXApp appName],
  500.      "StarShipCycleCount"))];
  501.     
  502.     
  503.     cell = atoi(NXGetDefaultValue([NXApp appName], "StarShipSound"));
  504.     if(cell)
  505.         [soundMatrix selectCellAt:0:0];
  506.     else
  507.         [soundMatrix selectCellAt:1:0];
  508.     return self;
  509. }
  510.  
  511. - writeDefaults:sender
  512. {
  513. int tag;
  514. char ctag[2];
  515.  
  516.     NXWriteDefault([NXApp appName], "StarShipAnimationSpeed",
  517.      [animationSlider stringValue]);
  518.     
  519.     NXWriteDefault([NXApp appName], "StarShipObjectSpeed",
  520.      [objectSpeedSlider stringValue]);
  521.  
  522.     NXWriteDefault([NXApp appName], "StarShipStarSpeed",
  523.      [starSpeedSlider stringValue]);
  524.     
  525.     NXWriteDefault([NXApp appName], "StarShipIntervalTime",
  526.      [objectIntervalSlider stringValue]);
  527.     
  528.     NXWriteDefault([NXApp appName], "StarShipCycleCount",
  529.      [cycleCountSlider stringValue]);
  530.     
  531.     tag = [[soundMatrix selectedCell] tag];
  532.     sprintf(ctag,"%d",tag);
  533.     NXWriteDefault([NXApp appName], "StarShipSound",ctag);
  534.     return self;
  535. }
  536.  
  537. port_t *xmach_sleep_install(void)
  538. {
  539.     port_t            *port;
  540.  
  541.     NX_MALLOC(port, port_t, sizeof(port_t));
  542.     port_allocate(task_self(), port);
  543.     
  544.     return(port);
  545. }
  546.  
  547. void xmach_sleep_remove(port_t *port)
  548. {
  549.     port_deallocate(task_self(), *port);
  550.     NX_FREE(port);
  551. }
  552.  
  553. void xmach_sleep(port_t *port, msg_timeout_t msecs)
  554. {
  555.     msg_header_t    h;
  556.  
  557.     h.msg_size    = sizeof(h);
  558.     h.msg_local_port = *port;
  559.  
  560.     msg_receive(&h, RCV_TIMEOUT, msecs);
  561. }
  562. - viewScreenResized:(NXRect *)screenRect
  563. {
  564.     viewScreenResized = YES;
  565.     NXSetRect(&newViewScreenSize,screenRect->origin.x,
  566.     screenRect->origin.y,screenRect->size.width, 
  567.     screenRect->size.height);
  568.     return self;
  569. }
  570. @end
  571.  
  572.  
  573.